package com.goodmr.passport.webapp.aspect;

import com.goodmr.passport.util.NetUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求日志收集
 *
 * @author <a href="mailto:bingdong13@msn.com">bigo</a>
 */
@Aspect
@Component
@Slf4j
public class RequestLogAspect {

    private ThreadLocal<Map<String, Object>> threadLocal = new ThreadLocal<>();

    @Pointcut("execution(public * com.goodmr.passport.webapp.controller..*(..))")
    public void webRequestLog() {}

    @Before("webRequestLog()")
    public void doBefore(JoinPoint joinPoint) {

        long beginTime = System.currentTimeMillis();

        log.info("doBefore[{}]", beginTime);

        // 接收到请求，记录请求内容
        HttpServletRequest request = NetUtil.httpServletRequest();

        Map<String, Object> operatorLog = Collections.synchronizedMap(new HashMap<String, Object>());

        operatorLog.put("beanName", joinPoint.getSignature().getDeclaringTypeName());
        operatorLog.put("methodName", joinPoint.getSignature().getName());

        operatorLog.put("reuestTime", beginTime);
        operatorLog.put("uri", request.getRequestURI());
        operatorLog.put("remoteAddr", NetUtil.getIpAddr(request));
        operatorLog.put("user", request.getSession().getAttribute("user"));
        operatorLog.put("sessionId", request.getSession().getId());

        threadLocal.set(operatorLog);
    }

    @AfterReturning(returning = "result", pointcut = "webRequestLog()")
    public void doAfterReturning(Object result) {

        long endTime = System.currentTimeMillis();

        log.info("doAfterReturning[{}]", endTime);

        // 处理完请求，返回内容
        Map<String, Object> operatorLog = threadLocal.get();
        long beginTime = (Long) operatorLog.get("reuestTime");

        log.info("请求耗时：{} ms ", endTime - beginTime);
        log.info("请求URL：{}", operatorLog.get("uri"));
        log.info("请求处理者：{}::{}", operatorLog.get("beanName"), operatorLog.get("methodName"));
        log.info("response：{}", result);
    }
}
